<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>团队选休系统</title>
    <link rel="stylesheet" href="./elementplus/index.min.css">
    <!-- <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/element-plus/2.4.4/index.min.css"> -->
    <script src="./elementplus/zh-cn.min.js"></script>
    <script src="./vue/vue.global.min.js"></script>
    <script src="./elementplus/index.full.min.js"></script>
    <script src="./axios/axios.min.js"></script>

    <style>
        body {
            margin: 0;
            padding: 0;
            font-family: "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
            overflow-x: hidden;
        }

        .app-container {
            max-width: 100%;
            margin: 0 auto;
            padding: 5px;
            box-sizing: border-box;
        }

        @media screen and (min-width: 768px) {
            .app-container {
                max-width: 500px;
                padding: 10px;
            }

            .calendar-day {
                min-height: 40px;
                font-size: 0.9rem;
            }

            .calendar-day .member-name {
                font-size: 0.7rem;
            }

            .calendar-weekdays {
                font-size: 0.9rem;
            }

            .el-tabs__item {
                padding: 0 10px;
                font-size: 0.9rem;
                height: 32px;
                line-height: 32px;
            }

            .header h1 {
                font-size: 1.3rem;
            }

            .calendar-header span {
                font-size: 1rem;
            }
        }

        .header {
            background-color: #409EFF;
            color: white;
            text-align: center;
            padding: 10px;
            margin-bottom: 10px;
            position: sticky;
            top: 0;
            z-index: 100;
        }

        .header h1 {
            margin: 0;
            font-size: 1.1rem;
        }



        .el-tabs {
            position: relative;
            z-index: 0;
        }

        .el-tabs__nav-wrap {
            margin-bottom: 10px;
        }

        .el-tabs__nav {
            white-space: nowrap;
            overflow-x: auto;
            -webkit-overflow-scrolling: touch;
            margin: 0;
        }

        .el-tabs__item {
            padding: 0 8px;
            font-size: 0.8rem;
            flex-shrink: 0;
            color: #606266;
            text-align: left;
            margin: 0;
            position: relative;
        }
        .el-tabs__item:not(:first-child) {
            margin-left: 0 !important;
        }
        .el-tabs__item.is-active {
            color: #fff;
            background-color: #409EFF;
        }
        .el-tabs__item:hover {
            color: #606266;
        }
        .el-tabs__item.is-active:hover {
            color: #fff;
        }

        .calendar-container {
            margin-top: 10px;
            overflow: hidden;
        }

        .calendar-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 10px;
            flex-wrap: wrap;
            gap: 8px;
        }

        .calendar-header span {
            font-size: 1rem;
            font-weight: bold;
        }

        .calendar-weekdays {
            display: grid;
            grid-template-columns: repeat(7, 1fr);
            text-align: center;
            margin-bottom: 5px;
            font-size: 0.8rem;
            gap: 5px;
        }

        .calendar-days {
            display: grid;
            grid-template-columns: repeat(7, 1fr);
            gap: 5px;
        }

        .calendar-day {
            aspect-ratio: 1;
            min-height: 25px;
            cursor: pointer;
            border-radius: 4px;
            position: relative;
            font-size: 0.8rem;
            padding: 4px 2px 2px;
            border: 1px solid #dcdfe6;
            background-color: #fff;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
            text-align: center;
            overflow: hidden;
        }

        .calendar-day .date-number {
            margin-top: 0;
        }

        .calendar-day .member-name {
            margin-top: 2px;
            font-size: 0.6rem;
            text-align: center;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space:pre-wrap;
            padding: 0 2px;

        }

        .calendar-day.selected {
            color: white;
            border-color: transparent;
        }

        .calendar-day.selected .member-name {
            margin-top: 2px;
        }

        .calendar-day.other-month {
            visibility: hidden;
            border: none;
            box-shadow: none;
        }

        .calendar-day:hover {
            background-color: #f5f7fa;
            transform: translateY(-2px);
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        }

        .action-buttons {
            margin: 10px 0;
            display: flex;
            gap: 8px;
            flex-wrap: wrap;
        }

        /* 移动端弹窗样式 */
        @media screen and (max-width: 768px) {
            .el-dialog {
                width: 90% !important;
                margin: 0 auto;
                max-height: 90vh;
                overflow-y: auto;
            }

            .el-dialog__body {
                padding: 15px;
            }

            .el-form-item__label {
                width: 100% !important;
                text-align: center;
                margin-bottom: 5px;
            }

            .el-form-item__content {
                margin-left: 0 !important;
                display: flex;
                justify-content: center;
            }

            .el-input-number {
                width: 100%;
                max-width: 200px;
            }

            .el-input {
                width: 100%;
                max-width: 200px;
            }

            .el-dialog__footer {
                padding: 10px 15px;
                text-align: center;
            }

            .el-tabs__nav {
                padding: 0 20px;
            }

            .el-tabs__item {
                padding: 0 5px;
                font-size: 0.7rem;
            }


        }

        @media screen and (min-width: 768px) {
            .calendar-day {
                min-height: 30px;
                font-size: 0.9rem;
                padding: 8px 2px 2px;
            }

            .calendar-day .date-number {
                margin-top: 0;
            }

            .calendar-day .member-name {
                margin-top: 10px;
                font-size: 0.7rem;
            }

            .calendar-weekdays {
                font-size: 0.9rem;
                gap: 8px;
            }

            .calendar-days {
                gap: 8px;
            }
        }

        .custom-tabs {
            margin-bottom: 10px;
            position: relative;
            width: 100%;
            overflow: hidden;
        }
        .custom-tabs-nav {
            display: flex;
            gap: 4px;
            padding: 4px;
            background-color: #f5f7fa;
            border-radius: 4px;
            overflow-x: auto;
            padding-bottom: 4px;
            width: 100%;
        }

        .custom-tab-item {
            padding: 0 12px;
            height: 28px;
            line-height: 28px;
            font-size: 0.8rem;
            color: #606266;
            background-color: #fff;
            border-radius: 4px;
            cursor: pointer;
            white-space: nowrap;
            flex-shrink: 0;
            user-select: none;
            -webkit-user-select: none;
        }
        .custom-tab-item.active {
            color: #fff;
            background-color: #409EFF;
        }

        @media screen and (min-width: 768px) {
            .custom-tab-item {
                padding: 0 16px;
                height: 32px;
                line-height: 32px;
                font-size: 0.9rem;
            }
        }
    </style>
</head>

<body>
    <div class="header">
        <h1>团队选休系统</h1>
    </div>
    <div class="app-container">
        <!-- 操作按钮 -->
        <div class="action-buttons" style="margin-bottom: 20px;">
            <el-button type="primary" size="small" @click="showAddMemberDialog">添加成员</el-button>
            <el-button type="warning" size="small" @click="clearCurrentMonth">清空当前月选休</el-button>
            <el-button type="danger" size="small" @click="clearAll">清空所有选休数据</el-button>
            <el-button v-if="activeMember" type="danger" size="small" @click="deleteMember(parseInt(activeMember))">删除成员</el-button>
        </div>

        <!-- 成员选项卡 -->
        <div class="custom-tabs" v-if="members.length > 0">
            <div class="custom-tabs-nav">
                <div
                    v-for="member in members"
                    :key="member.id"
                    class="custom-tab-item"
                    :class="{ active: activeMember === member.id.toString() }"
                    @click="activeMember = member.id.toString()"
                    @touchstart="handleTouchStart"
                    @touchend="handleTouchEnd"
                >
                    {{ member.name }} ({{ getCurrentMonthSelectedDays(member) }}/{{ member.maxRestDays }})
                </div>
            </div>

        </div>

        <!-- 日历组件 -->
        <div class="calendar-container">
            <div class="calendar-header">
                <el-button @click="prevMonth">上个月</el-button>
                <span>{{ currentYear }}年{{ currentMonth + 1 }}月</span>
                <el-button @click="nextMonth">下个月</el-button>
            </div>
            <div class="calendar-weekdays">
                <div v-for="day in weekdays" :key="day">{{ day }}</div>
            </div>
            <div class="calendar-days">
                <div v-for="(day, index) in calendarDays" :key="index" class="calendar-day" :class="{
                        'selected': isSelected(day),
                        'other-month': !day
                    }" :style="{ backgroundColor: isSelected(day) ? getDateColor(day) : 'transparent' }"
                    @click="day && handleDateClick(day)">
                    <span class="date-number">{{ day ? day.getDate() : '' }}</span>
                    <div v-if="isSelected(day)" class="member-name">{{ getDateMemberName(day) }}</div>
                </div>
            </div>
            <!-- 在线人数显示 -->
            <div class="online-count" style="text-align: center; margin-top: 15px; color: #409EFF;">
                当前在线人数：{{ onlineCount }}
            </div>
        </div>

        <!-- 添加成员对话框 -->
        <el-dialog v-model="dialogVisible" title="添加新成员" :width="windowWidth > 768 ? '30%' : '90%'" align-center>
            <el-form :model="newMember" label-width="100px" label-position="top">
                <el-form-item label="姓名" required>
                    <el-input v-model="newMember.name" placeholder="请输入成员姓名"></el-input>
                </el-form-item>
                <el-form-item label="最大选休天数" required>
                    <el-input-number v-model="newMember.maxRestDays" :min="1" :max="31"
                        style="width: 100%"></el-input-number>
                </el-form-item>
            </el-form>
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="dialogVisible = false">取消</el-button>
                    <el-button type="primary" @click="addMember">确定</el-button>
                </span>
            </template>
        </el-dialog>
    </div>

</body>
<script>
    const { createApp, ref, onMounted, watch, computed, onUnmounted } = Vue

    const app = createApp({
        setup() {
            const members = ref([])
            const activeMember = ref('')
            const currentDate = ref(new Date())
            const currentYear = ref(new Date().getFullYear())
            const currentMonth = ref(new Date().getMonth())
            const dialogVisible = ref(false)
            const newMember = ref({
                name: '',
                maxRestDays: 6
            })
            const weekdays = ['日', '一', '二', '三', '四', '五', '六']
            const ws = ref(null)
            const windowWidth = ref(window.innerWidth)
            const wsReconnectAttempts = ref(0)
            const maxReconnectAttempts = 5
            const heartbeatInterval = ref(null)
            const isWsConnected = ref(false)
            const wsConnectionTimeout = ref(null)
            const isUpdating = ref(false)
            const onlineCount = ref(0)

            // 添加触摸滑动相关变量
            const touchStartX = ref(0)
            const touchEndX = ref(0)
            const swipeThreshold = 30 // 降低滑动阈值

            // 预定义的颜色列表
            const predefinedColors = [
                'rgba(82, 193, 199, 0.8)', // 蓝色
                'rgba(103, 194, 58, 0.8)', // 绿色
                'rgba(230, 162, 60, 0.8)', // 橙色
                'rgba(245, 108, 108, 0.8)', // 红色
                'rgba(144, 147, 153, 0.8)', // 灰色
                'rgba(142, 68, 173, 0.8)', // 紫色
                'rgba(22, 160, 133, 0.8)', // 青色
                'rgba(243, 156, 18, 0.8)', // 黄色
                'rgba(26, 188, 156, 0.8)', // 青色
                'rgba(52, 152, 219, 0.8)', // 蓝色
                'rgba(231, 76, 60, 0.8)', // 红色
                'rgba(46, 204, 113, 0.8)', // 绿色
                'rgba(155, 89, 182, 0.8)', // 紫色
                'rgba(52, 73, 94, 0.8)', // 深蓝
                'rgba(241, 196, 15, 0.8)'  // 黄色
            ]

            // 根据成员索引获取颜色
            const getMemberColor = (index) => {
                return predefinedColors[index % predefinedColors.length]
            }

            // 计算当前月份的所有日期
            const calendarDays = computed(() => {
                const days = []
                const firstDay = new Date(currentYear.value, currentMonth.value, 1)
                const lastDay = new Date(currentYear.value, currentMonth.value + 1, 0)
                const firstDayWeek = firstDay.getDay()

                // 添加上个月的占位
                for (let i = 0; i < firstDayWeek; i++) {
                    days.push(null)
                }

                // 添加当前月的日期
                for (let i = 1; i <= lastDay.getDate(); i++) {
                    const date = new Date(currentYear.value, currentMonth.value, i)
                    days.push(date)
                }

                // 添加下个月的占位，确保总数为42（6行7列）
                const remainingDays = 42 - days.length
                for (let i = 0; i < remainingDays; i++) {
                    days.push(null)
                }

                return days
            })

            // 判断是否是当前月份
            const isCurrentMonth = (date) => {
                return date !== null && date.getMonth() === currentMonth.value
            }

            // 上个月
            const prevMonth = () => {
                if (currentMonth.value === 0) {
                    currentYear.value--
                    currentMonth.value = 11
                } else {
                    currentMonth.value--
                }
            }

            // 下个月
            const nextMonth = () => {
                if (currentMonth.value === 11) {
                    currentYear.value++
                    currentMonth.value = 0
                } else {
                    currentMonth.value++
                }
            }

            // 初始化 WebSocket 连接
            const initWebSocket = () => {
                // 如果已经存在连接且状态为 OPEN 或 CONNECTING，则不创建新连接
                if (ws.value && (ws.value.readyState === WebSocket.OPEN || ws.value.readyState === WebSocket.CONNECTING)) {
                    console.log('WebSocket 已连接或正在连接中，跳过重连');
                    return;
                }

                // 清理旧的连接
                if (ws.value) {
                    ws.value.close();
                    ws.value = null;
                }

                const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
                const wsUrl = `${protocol}//${window.location.hostname}:3001`;

                try {
                    console.log('正在建立 WebSocket 连接...');
                    ws.value = new WebSocket(wsUrl);

                    // 设置连接超时
                    if (wsConnectionTimeout.value) {
                        clearTimeout(wsConnectionTimeout.value);
                    }
                    wsConnectionTimeout.value = setTimeout(() => {
                        if (ws.value && ws.value.readyState !== WebSocket.OPEN) {
                            console.log('连接超时，关闭连接');
                            ws.value.close();
                        }
                    }, 5000);

                    ws.value.onopen = () => {
                        console.log('WebSocket 连接已建立');
                        clearTimeout(wsConnectionTimeout.value);
                        isWsConnected.value = true;
                        wsReconnectAttempts.value = 0;
                        startHeartbeat();
                        // 连接建立后立即获取最新数据
                        fetchMembers();
                    };

                    ws.value.onmessage = (event) => {
                        try {
                            const message = JSON.parse(event.data);
                            if (message.type === 'init' || message.type === 'update') {
                                // 分别处理onlineCount和members数据
                                if (typeof message.data.onlineCount === 'number') {
                                    onlineCount.value = message.data.onlineCount;
                                }
                                if (Array.isArray(message.data.members)) {
                                    members.value = message.data.members;
                                    if (members.value.length > 0 && !activeMember.value) {
                                        activeMember.value = members.value[0].id.toString();
                                    }
                                } else if (message.data.members === undefined) {
                                    // 如果没有members数据，保持现有数据不变
                                    console.log('没有收到members数据');
                                } else {
                                    console.error('收到的members数据格式不正确:', message.data.members);
                                    members.value = []; // 重置为空数组
                                }
                            } else if (message.type === 'pong') {
                                console.log('收到心跳响应');
                            }
                        } catch (error) {
                            console.error('处理消息错误:', error);
                            members.value = []; // 发生错误时重置为空数组
                        }
                    };

                    ws.value.onerror = (error) => {
                        console.error('WebSocket 错误:', error);
                        isWsConnected.value = false;
                        stopHeartbeat();
                        clearTimeout(wsConnectionTimeout.value);
                        members.value = []; // 发生错误时重置为空数组
                    };

                    ws.value.onclose = () => {
                        console.log('WebSocket 连接已关闭');
                        isWsConnected.value = false;
                        stopHeartbeat();
                        clearTimeout(wsConnectionTimeout.value);
                        members.value = []; // 连接关闭时重置为空数组

                        // 指数退避重连
                        const delay = Math.min(1000 * Math.pow(2, wsReconnectAttempts.value), 30000);
                        if (wsReconnectAttempts.value < maxReconnectAttempts) {
                            console.log(`将在 ${delay / 1000} 秒后尝试重新连接`);
                            setTimeout(() => {
                                wsReconnectAttempts.value++;
                                initWebSocket();
                            }, delay);
                        } else {
                            console.log('达到最大重连次数，请刷新页面重试');
                            ElementPlus.ElMessage.error('连接已断开，请刷新页面重试');
                        }
                    };
                } catch (error) {
                    console.error('创建WebSocket连接失败:', error);
                    clearTimeout(wsConnectionTimeout.value);
                    members.value = []; // 创建连接失败时重置为空数组
                }
            };

            // 开始心跳检测
            const startHeartbeat = () => {
                stopHeartbeat();
                heartbeatInterval.value = setInterval(() => {
                    if (ws.value && ws.value.readyState === WebSocket.OPEN) {
                        try {
                            ws.value.send(JSON.stringify({ type: 'ping' }));
                        } catch (error) {
                            console.error('发送心跳失败:', error);
                            ws.value.close();
                        }
                    }
                }, 30000);
            };

            // 停止心跳检测
            const stopHeartbeat = () => {
                if (heartbeatInterval.value) {
                    clearInterval(heartbeatInterval.value);
                    heartbeatInterval.value = null;
                }
            };

            // 组件挂载时初始化 WebSocket
            onMounted(() => {
                console.log('组件已挂载');
                initWebSocket();
                fetchMembers();
                window.addEventListener('resize', () => {
                    windowWidth.value = window.innerWidth;
                });
            });

            // 组件卸载时清理所有资源
            onUnmounted(() => {
                stopHeartbeat();
                if (wsConnectionTimeout.value) {
                    clearTimeout(wsConnectionTimeout.value);
                }
                if (ws.value) {
                    ws.value.close();
                    ws.value = null;
                }
            });

            // 监听网络状态变化
            window.addEventListener('online', () => {
                console.log('网络已连接');
                if (!isWsConnected.value) {
                    initWebSocket();
                }
            });

            window.addEventListener('offline', () => {
                console.log('网络已断开');
                if (ws.value) {
                    ws.value.close();
                }
            });

            // 获取成员列表
            const fetchMembers = async () => {
                try {
                    const response = await axios.get('/api/members')
                    if (response.data && Array.isArray(response.data.members)) {
                        members.value = response.data.members
                        if (members.value.length > 0 && !activeMember.value) {
                            activeMember.value = members.value[0].id.toString()
                        }
                    } else {
                        console.error('获取的成员数据格式不正确:', response.data);
                        members.value = []; // 数据格式不正确时重置为空数组
                    }
                } catch (error) {
                    console.error('获取成员列表失败:', error)
                    ElementPlus.ElMessage.error('获取成员列表失败')
                    members.value = []; // 获取失败时重置为空数组
                }
            }

            // 添加成员
            const addMember = async () => {
                if (!newMember.value.name.trim()) {
                    ElementPlus.ElMessage.warning('请输入成员姓名');
                    return;
                }
                try {
                    const response = await axios.post('/api/members', {
                        name: newMember.value.name,
                        maxRestDays: newMember.value.maxRestDays
                    })
                    // 不再手动添加成员，等待 WebSocket 推送更新
                    dialogVisible.value = false
                    newMember.value = { name: '', maxRestDays: 6 }
                    ElementPlus.ElMessage.success('添加成员成功')
                } catch (error) {
                    console.error('添加成员失败:', error)
                    ElementPlus.ElMessage.error('添加成员失败')
                }
            }

            // 删除成员
            const deleteMember = async (id) => {
                // 防止重复点击
                if (isUpdating.value) {
                    return;
                }

                isUpdating.value = true;

                try {
                    await ElementPlus.ElMessageBox.confirm(
                        '确定要删除该成员吗？',
                        '提示',
                        {
                            type: 'warning',
                            confirmButtonText: '确定',
                            cancelButtonText: '取消',
                            closeOnClickModal: false, // 防止误触
                            closeOnPressEscape: false, // 防止误触
                            distinguishCancelAndClose: true // 区分取消和关闭
                        }
                    );

                    const response = await axios.delete(`/api/members/${id}`);
                    if (response.data && response.data.success) {
                        members.value = members.value.filter(member => member.id !== id);
                        if (activeMember.value === id.toString()) {
                            activeMember.value = members.value[0]?.id.toString() || '';
                        }
                        ElementPlus.ElMessage.success('删除成员成功');
                    } else {
                        throw new Error('删除失败');
                    }
                } catch (error) {
                    if (error === 'cancel' || error === 'close') {
                        // 用户取消删除，不做任何处理
                    } else {
                        console.error('删除成员失败:', error);
                        ElementPlus.ElMessage.error('删除成员失败，请重试');
                    }
                } finally {
                    isUpdating.value = false;
                }
            }

            // 更新选休日期
            const updateSelectedDays = async (memberId, selectedDays) => {
                try {
                    console.log('更新选休日期:', memberId, selectedDays);
                    const response = await axios.put(`/api/members/${memberId}/days`, {
                        selectedDays: selectedDays
                    });
                    console.log('更新成功:', response.data);
                    const member = members.value.find(m => m.id === memberId);
                    if (member) {
                        member.selectedDays = selectedDays;
                    }
                } catch (error) {
                    console.error('更新选休日期失败:', error);
                    throw error; // 抛出错误以便上层处理
                }
            }

            // 获取当前月份的选中天数
            const getCurrentMonthSelectedDays = (member) => {
                if (!member) return 0;
                const currentYearMonth = `${currentYear.value}-${String(currentMonth.value + 1).padStart(2, '0')}`;
                return member.selectedDays[currentYearMonth]?.length || 0;
            }

            // 判断日期是否被选中
            const isSelected = (date) => {
                if (!date || !isCurrentMonth(date)) return false;
                const yearMonth = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
                const dateStr = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
                return members.value.some(member => 
                    member.selectedDays[yearMonth]?.includes(dateStr)
                );
            }

            // 获取日期的选中颜色
            const getDateColor = (date) => {
                if (!date || !isCurrentMonth(date)) return 'transparent';
                const yearMonth = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
                const dateStr = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
                const member = members.value.find(m => m.selectedDays[yearMonth]?.includes(dateStr));
                return member?.color || 'transparent';
            }

            // 获取日期的选中成员名称
            const getDateMemberName = (date) => {
                if (!date || !isCurrentMonth(date)) return '';
                const yearMonth = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
                const dateStr = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
                const member = members.value.find(m => m.selectedDays[yearMonth]?.includes(dateStr));
                return member?.name || '';
            }

            // 处理日期点击
            const handleDateClick = async (date) => {
                if (isUpdating.value) {
                    ElementPlus.ElMessage.warning('正在处理中，请稍候');
                    return;
                }

                const member = members.value.find(m => m.id.toString() === activeMember.value);
                if (!member) {
                    console.log('未找到当前成员');
                    return;
                }

                const yearMonth = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
                // 修复时区问题，使用本地时间
                const dateStr = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;

                // 检查该日期是否已被其他成员选中
                const isDateOccupied = members.value.some(m =>
                    m.id !== member.id && m.selectedDays[yearMonth]?.includes(dateStr)
                );

                if (isDateOccupied) {
                    ElementPlus.ElMessage.warning('该日期已被其他成员选中');
                    return;
                }

                // 确保 selectedDays[yearMonth] 存在
                if (!member.selectedDays[yearMonth]) {
                    member.selectedDays[yearMonth] = [];
                }

                const index = member.selectedDays[yearMonth].indexOf(dateStr);
                isUpdating.value = true;

                try {
                    if (index === -1) {
                        if (member.selectedDays[yearMonth].length >= member.maxRestDays) {
                            ElementPlus.ElMessage.warning(`本月已达到最大选休天数 ${member.maxRestDays}`);
                            return;
                        }
                        member.selectedDays[yearMonth].push(dateStr);
                    } else {
                        member.selectedDays[yearMonth].splice(index, 1);
                    }

                    // 如果月份的数组为空，删除该月份键
                    if (member.selectedDays[yearMonth].length === 0) {
                        delete member.selectedDays[yearMonth];
                    }

                    await updateSelectedDays(member.id, {...member.selectedDays});
                } catch (error) {
                    console.error('更新选休日期失败:', error);
                    ElementPlus.ElMessage.error(error.response?.data?.error || '更新选休日期失败');
                    // 恢复原始状态
                    if (index === -1) {
                        member.selectedDays[yearMonth]?.pop();
                    } else {
                        member.selectedDays[yearMonth]?.splice(index, 0, dateStr);
                    }
                } finally {
                    isUpdating.value = false;
                }
            }

            // 清空所有选休数据
            const clearAll = async () => {
                try {
                    await ElementPlus.ElMessageBox.confirm('确定要清空所有选休数据吗？', '提示', {
                        type: 'warning'
                    })
                    await axios.post('/api/clear')
                    members.value.forEach(member => {
                        member.selectedDays = {}
                    })
                    ElementPlus.ElMessage.success('清空成功')
                } catch (error) {
                    if (error !== 'cancel') {
                        console.error('清空失败:', error)
                        ElementPlus.ElMessage.error('清空失败')
                    }
                }
            }

            // 切换成员时更新日历显示
            const handleTabClick = () => {
                // 强制更新日历视图
                currentDate.value = new Date()
            }

            // 处理触摸开始事件
            const handleTouchStart = (e) => {
                touchStartX.value = e.touches[0].clientX
            }

            // 处理触摸结束事件
            const handleTouchEnd = (e) => {
                touchEndX.value = e.changedTouches[0].clientX
                const diff = touchStartX.value - touchEndX.value

                if (Math.abs(diff) > swipeThreshold) {
                    const currentIndex = members.value.findIndex(m => m.id.toString() === activeMember.value)

                    if (diff > 0 && currentIndex < members.value.length - 1) {
                        // 向左滑动，切换到下一个
                        activeMember.value = members.value[currentIndex + 1].id.toString()
                    } else if (diff < 0 && currentIndex > 0) {
                        // 向右滑动，切换到上一个
                        activeMember.value = members.value[currentIndex - 1].id.toString()
                    }
                }
            }

            // 监听成员变化，为每个成员分配颜色
            watch(members, (newMembers) => {
                newMembers.forEach((member, index) => {
                    member.color = getMemberColor(index)
                })
            }, { deep: true, immediate: true })

            // 监听成员变化
            watch(members, (newVal) => {
                console.log('成员数据变化:', newVal);
            }, { deep: true });

            // 监听当前选中的成员
            watch(activeMember, (newVal) => {
                console.log('当前选中的成员变化:', newVal);
            });

            // 获取当前选中的成员
            const getCurrentMember = () => {
                return members.value.find(m => m.id.toString() === activeMember.value);
            }

            // 清空当前月份选休数据
            const clearCurrentMonth = async () => {
                try {
                    await ElementPlus.ElMessageBox.confirm(
                        `确定要清空 ${currentYear.value}年${currentMonth.value + 1}月 的所有选休数据吗？`, 
                        '提示', 
                        {
                            type: 'warning'
                        }
                    );
                    
                    await axios.post('/api/clear-current-month', {
                        year: currentYear.value,
                        month: currentMonth.value
                    });
                    
                    const yearMonth = `${currentYear.value}-${String(currentMonth.value + 1).padStart(2, '0')}`;
                    members.value.forEach(member => {
                        if (member.selectedDays[yearMonth]) {
                            delete member.selectedDays[yearMonth];
                        }
                    });
                    
                    ElementPlus.ElMessage.success('清空当前月份选休数据成功');
                } catch (error) {
                    if (error !== 'cancel') {
                        console.error('清空当前月份选休数据失败:', error);
                        ElementPlus.ElMessage.error('清空当前月份选休数据失败');
                    }
                }
            };

            return {
                members,
                activeMember,
                currentDate,
                currentYear,
                currentMonth,
                dialogVisible,
                newMember,
                weekdays,
                calendarDays,
                isCurrentMonth,
                prevMonth,
                nextMonth,
                showAddMemberDialog: () => dialogVisible.value = true,
                addMember,
                deleteMember,
                clearAll,
                handleDateClick,
                isSelected,
                getDateColor,
                getDateMemberName,
                handleTabClick,
                windowWidth,
                handleTouchStart,
                handleTouchEnd,
                getCurrentMember,
                getCurrentMonthSelectedDays,
                clearCurrentMonth,
                onlineCount
            }
        }
    })

    app.use(ElementPlus, {
        locale: ElementPlusLocaleZhCn
    })
    app.mount('.app-container')
</script>


</html>